home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / Kibitz⁄THINK C / DoEvent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-21  |  13.6 KB  |  563 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:        Kibitz
  5. ** File:        doevent.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1991 Apple Computer, Inc.
  9. ** All rights reserved.
  10. */
  11.  
  12.  
  13.  
  14. /*****************************************************************************/
  15.  
  16.  
  17.  
  18. #include "Kibitz.h"                /* Get the Kibitz includes/typedefs, etc.    */
  19. #include "KibitzCommon.h"        /* Get the stuff in common with rez.        */
  20. #include "Kibitz.protos"        /* Get the prototypes for Kibitz.            */
  21.  
  22. #ifndef __DESK__
  23. #include <Desk.h>
  24. #endif
  25.  
  26. #ifndef __DISKINIT__
  27. #include <DiskInit.h>
  28. #endif
  29.  
  30. #ifndef __ERRORS__
  31. #include <Errors.h>
  32. #endif
  33.  
  34. #ifndef __MENUS__
  35. #include <Menus.h>
  36. #endif
  37.  
  38. #ifndef __TEXTEDITCONTROL__
  39. #include "TextEditControl.h"
  40. #endif
  41.  
  42. #ifndef __TOOLUTILS__
  43. #include <ToolUtils.h>
  44. #endif
  45.  
  46. #ifndef __UTILITIES__
  47. #include "Utilities.h"
  48. #endif
  49.  
  50.  
  51.  
  52. /*****************************************************************************/
  53.  
  54.  
  55.  
  56. extern Cursor    *gCurrentCursor;
  57.  
  58.  
  59.  
  60. /*****************************************************************************/
  61. /*****************************************************************************/
  62.  
  63.  
  64.  
  65. /* Do the right thing for an event.  Determine what kind of event it is, and
  66. ** call the appropriate routines.
  67. */
  68.  
  69. #pragma segment Main
  70. void    DoEvent(EventRecord *event)
  71. {
  72.     short            part, err;
  73.     WindowPtr        window;
  74.     char            key;
  75.     Point            aPoint;
  76.     FileRecHndl        frHndl;
  77.     ControlHandle    ctl;
  78.     long            tick;
  79.     Rect            boardRct;
  80.  
  81.     switch(event->what) {
  82.  
  83.         case mouseDown:
  84.             gCurrentCursor = nil;
  85.                 /* No shortcuts when we recalculate the cursor region. */
  86.  
  87.             part = FindWindow(event->where, &window);
  88.             if (part != inContent) DoSetCursor(&QD(arrow));
  89.  
  90.             switch(part) {
  91.  
  92.                 case inContent:
  93.                     if (window != FrontWindow()) {
  94.                         SelectWindow(window);
  95.                         if (IsAppWindow(window)) {
  96.                             DoUpdate(window);
  97.                             boardRct = GlobalBoardRect(window);
  98.                             if (PtInRect(event->where, &boardRct))
  99.                                 DoEvent(event);
  100.                         }
  101.                                     /* Do first click if over board. */
  102.                     } else
  103.                         DoContentClick(window, event);
  104.                     break;
  105.  
  106.                 case inDrag:            
  107.                     DragWindow(window, event->where, &QD(screenBits.bounds));
  108.                     break;        /* Pass screenBits.bounds to
  109.                                 ** get all gDevices. */
  110.  
  111.                 case inGoAway:
  112.                     if (TrackGoAway(window, event->where)) {
  113.                         CloseOneWindow(window, iClose);
  114.                     }
  115.                     break;
  116.  
  117.                 case inGrow:
  118.                     break;
  119.  
  120.                 case inMenuBar:        /* Process mouse menu command (if any). */
  121.                     AdjustMenus();
  122.                     DoMenuCommand(MenuSelect(event->where));
  123.                     break;
  124.  
  125.                 case inSysWindow:    /* Let the system handle the mouseDown. */
  126.                     SystemClick(event, window);
  127.                     break;
  128.  
  129.                 case inZoomIn:
  130.                 case inZoomOut:
  131.                     if (TrackBox(window, event->where, part))
  132.                         ZoomToWindowDevice(window, 0, 0, part, true);
  133.                     break;
  134.  
  135.             }
  136.             break;
  137.  
  138.         case activateEvt:
  139.             gCurrentCursor = nil;
  140.                 /* No shortcuts when we recalculate the cursor region. */
  141.  
  142.             DoActivate((WindowPtr)event->message,
  143.                        (event->modifiers & activeFlag));
  144.             break;
  145.  
  146.         case autoKey:
  147.         case keyDown:                    /* Check for menukey equivalents. */
  148.             key = event->message & charCodeMask;
  149.             if (event->modifiers & cmdKey) {        /* Command key down. */
  150.                 if (event->what == keyDown) {
  151.                     AdjustMenus();
  152.                         /* Enable/disable/check menu items properly. */
  153.                     DoMenuCommand(MenuKey(key));
  154.                 }
  155.             }
  156.             else {
  157.                 if (!IsAppWindow(window = FrontWindow())) break;
  158.                 frHndl = (FileRecHndl)GetWRefCon(window);
  159.                 if (key == 0x03) {
  160.                     ctl = (*frHndl)->doc.sendMessage;
  161.                     if (!(*ctl)->contrlHilite) {
  162.                         HiliteControl(ctl, 1);
  163.                         tick = TickCount();
  164.                         while (TickCount() < tick + 10);
  165.                         HiliteControl(ctl, 0);
  166.                         SendMssg(frHndl, kTextMssg);
  167.                     }
  168.                 }
  169.                 else {
  170.                     if (CTEKey(event)) {
  171.                         AdjustMenus();        /* Avoid unnecessary DoCursor() and speed */
  172.                         return;                /* up TextEdit entry. */
  173.                     }
  174.                 }
  175.             }
  176.             break;
  177.  
  178.         case diskEvt:
  179.             gCurrentCursor = nil;
  180.                 /* No shortcuts when we recalculate the cursor region. */
  181.  
  182.             if (HiWord(event->message) != noErr) {
  183.                 SetPt(&aPoint, kDILeft, kDITop);
  184.                 err = DIBadMount(aPoint, event->message);
  185.             }
  186.             break;        /* It is not a bad idea to at least call DIBadMount
  187.                         ** in response to a diskEvt, so that the user can
  188.                         ** format a floppy.
  189.                         */
  190.         case kHighLevelEvent:
  191.             gCurrentCursor = nil;
  192.                 /* No shortcuts when we recalculate the cursor region. */
  193.  
  194.             DoHighLevelEvent(event);
  195.             break;
  196.  
  197.         case kOSEvent:
  198.             gCurrentCursor = nil;
  199.                 /* No shortcuts when we recalculate the cursor region. */
  200.  
  201.             switch ((event->message >> 24) & 0x0FF) {
  202.                     /* Must logical and with 0x0FF to get only low byte. */
  203.                     /* High byte of message. */
  204.  
  205.                 case kMouseMovedMessage:
  206.                     break;
  207.  
  208.                 case kSuspendResumeMessage:
  209.                         /* Suspend/resume is also an activate/deactivate. */
  210.                     gInBackground = !(event->message & kResumeMask);
  211.                     DoActivate(FrontWindow(), !gInBackground);
  212.                     break;
  213.             }
  214.             break;
  215.  
  216.         case updateEvt:
  217.             DoUpdate((WindowPtr)event->message);
  218.             break;
  219.  
  220.     }
  221.  
  222.     DoCursor(false, 0);
  223.     AdjustMenus();
  224. }
  225.  
  226.  
  227.  
  228. /*****************************************************************************/
  229.  
  230.  
  231.  
  232. /* This is called when a window is activated or deactivated. */
  233.  
  234. #pragma segment Main
  235. void    DoActivate(WindowPtr window, Boolean becomingActive)
  236. {
  237.     FileRecHndl        frHndl;
  238.     short            hilite;
  239.     ControlHandle    ctl;
  240.  
  241.     NotifyCancel();
  242.  
  243.     if (IsAppWindow(window)) {
  244.  
  245.         frHndl = (FileRecHndl)GetWRefCon(window);
  246.  
  247.         SetPort(window);
  248.         SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
  249.  
  250.         hilite = 0;
  251.         if (!becomingActive) hilite = 255;
  252.  
  253.         HiliteControl((*frHndl)->doc.gameSlider, hilite);
  254.         HiliteControl((*frHndl)->doc.resign, hilite);
  255.         HiliteControl((*frHndl)->doc.draw, hilite);
  256.  
  257.         if (!(*frHndl)->doc.twoPlayer) hilite = 255;
  258.  
  259.         HiliteControl(ctl = (*frHndl)->doc.sendMessage, hilite);
  260.         OutlineControl(ctl);
  261.         HiliteControl((*frHndl)->doc.beepOnMove, hilite);
  262.         HiliteControl((*frHndl)->doc.beepOnMssg, hilite);
  263.  
  264.         if (!SoundInputAvaliable()) hilite = 255;
  265.         HiliteControl((*frHndl)->doc.record, hilite);
  266.         if (!(*frHndl)->doc.sound) hilite = 255;
  267.         HiliteControl((*frHndl)->doc.sendSnd, hilite);
  268.  
  269.         if ((*frHndl)->doc.arrangeBoard) becomingActive = false;
  270.         CTEWindActivate(window, becomingActive);
  271.  
  272.         SetOrigin(0, 0);
  273.     }
  274. }
  275.  
  276.  
  277.  
  278. /*****************************************************************************/
  279.  
  280.  
  281.  
  282. /* This is called when an update event is received for a window.  It calls
  283. ** ImageDocument to draw the contents of an application window.  As an
  284. ** effeciency measure that does not have to be followed, it calls the drawing
  285. ** routine only if the visRgn is non-empty.  This will handle situations where
  286. ** calculations for drawing or drawing itself is very time-consuming.
  287. */
  288.  
  289. #pragma segment Main
  290. void    DoUpdate(WindowPtr window)
  291. {
  292.     if (IsAppWindow(window)) {
  293.         BeginUpdate(window);                /* This sets up the visRgn. */
  294.         if (!EmptyRgn(window->visRgn)) {    /* Draw if updating needs doing. */
  295.             SetPort(window);
  296.             ImageDocument((FileRecHndl)GetWRefCon(window), false);
  297.         }
  298.         EndUpdate(window);
  299.     }
  300. }
  301.  
  302.  
  303.  
  304. /*****************************************************************************/
  305.  
  306.  
  307.  
  308. /* This is called when a mouse-down event occurs in the content of a window.
  309. ** Other applications might want to call FindControl, TEClick, etc., to
  310. ** further process the click.
  311. */
  312.  
  313. #pragma segment Main
  314. void    DoContentClick(WindowPtr window, EventRecord *event)
  315. {
  316.     Boolean            invertBoard;
  317.     short            fromRow, fromCol, toRow, toCol, i, myColor;
  318.     short            fromSq, toSq, promotion, piece, item;
  319.     short            numLegalMoves, part, twoPlayer;
  320.     OSErr            err;
  321.     long            moveAmount, ref;
  322.     Point            clickLoc, releaseLoc;
  323.     Rect            boardRect, squareRect;
  324.     RgnHandle        dragRgn;
  325.     FileRecHndl        frHndl;
  326.     MoveListHndl    legalMoves;
  327.     DialogPtr        promoteDialog;
  328.     short            itemType, ctlNum;
  329.     Handle            itemHndl;
  330.     Rect            itemRect;
  331.     ControlHandle    ctlHit;
  332.  
  333.     if (!IsAppWindow(window)) return;
  334.  
  335.     frHndl = (FileRecHndl)GetWRefCon(window);
  336.     SetPort(window);
  337.     SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
  338.  
  339.     twoPlayer = (*frHndl)->doc.twoPlayer;
  340.  
  341.     clickLoc = event->where;
  342.     GlobalToLocal(&clickLoc);
  343.  
  344.     if (CTEClick(event)) {
  345.         SetOrigin(0, 0);
  346.         return;
  347.     }
  348.         /* If TextEdit control handled the click, we are done. */
  349.  
  350.     if (part = FindControl(clickLoc, window, &ctlHit)) {
  351.         ctlNum = ref = GetCRefCon(ctlHit);
  352.         if ((ref) && (ref < 10)) {
  353.             if (TrackControl(ctlHit, clickLoc, nil)) {
  354.                 switch (ctlNum) {
  355.                     case 1:
  356.                         SendMssg(frHndl, kTextMssg);
  357.                         break;
  358.                     case 2:
  359.                     case 3:
  360.                         SetCtlValue(ctlHit, GetCtlValue(ctlHit) ^ 1);
  361.                         break;
  362.                     case 4:
  363.                     case 5:
  364.                         SetCtlValue(ctlHit, 1);
  365.                         SetCtlValue((*frHndl)->doc.wbStart[5 - ctlNum], 0);
  366.                         (*frHndl)->doc.startColor = ctlNum - 4;
  367.                         break;
  368.                     case 6:
  369.                         EndTheGame(frHndl, kWhiteResigns + (*frHndl)->doc.myColor);
  370.                         UpdateGameStatus(frHndl);
  371.                         if (twoPlayer) {
  372.                             SendGame(frHndl, kIsMove);
  373.                                 /* Show the dialog at the other end. */
  374.                             SendGame(frHndl, kResync);
  375.                                 /* Make sure that simultaneous hits on the
  376.                                 ** resign button are taken care of. */
  377.                         }
  378.                         break;
  379.                     case 7:
  380.                         i = ((*frHndl)->doc.drawBtnState ^ 0x02);
  381.                         if (!twoPlayer) i = 0x06;
  382.                         if (i >= 0x06) EndTheGame(frHndl, kDrawGame);
  383.                         DrawButtonTitle(frHndl, i);
  384.                         if (twoPlayer) {
  385.                             SendGame(frHndl, kIsMove);
  386.                                 /* Show the dialog at the other end. */
  387.                             SendGame(frHndl, kResync);
  388.                                 /* Make sure that simultaneous hits on the
  389.                                 ** draw button are taken care of. */
  390.                         }
  391.                         break;
  392.                     case 8:
  393.                         err = RecordSound(frHndl);
  394.                         if ((err) && (err != userCanceledErr)) Alert(rErrorAlert, nil);
  395.                         break;
  396.                     case 9:
  397.                         SendMssg(frHndl, kSoundMssg);
  398.                         break;
  399.                 }
  400.             }
  401.         }
  402.         SetOrigin(0, 0);
  403.  
  404.         if (ctlHit == (*frHndl)->doc.gameSlider)
  405.             TrackControl(ctlHit, clickLoc, nil);
  406.  
  407.         return;
  408.     }
  409.  
  410.     if ((*frHndl)->fileState.readOnly) {
  411.         SetOrigin(0, 0);
  412.         return;
  413.     }                    /* Don't allow changes if read-only. */
  414.  
  415.     if ((*frHndl)->doc.arrangeBoard) {
  416.         DoArrangeBoard(frHndl, clickLoc);
  417.         return;
  418.     }
  419.  
  420.     SetOrigin(0, 0);
  421.  
  422.     invertBoard = (*frHndl)->doc.invertBoard;
  423.  
  424.     boardRect = BoardRect();
  425.     if (!PtInRect(clickLoc, &boardRect)) return;
  426.  
  427.     fromRow = (clickLoc.v - kBoardVOffset) / kBoardSqSize;
  428.     fromCol = (clickLoc.h - kBoardHOffset) / kBoardSqSize;
  429.  
  430.     squareRect.top    = kBoardVOffset + fromRow * kBoardSqSize;
  431.     squareRect.left   = kBoardHOffset + fromCol * kBoardSqSize;
  432.     squareRect.bottom = squareRect.top  + kBoardSqSize + 2;
  433.     squareRect.right  = squareRect.left + kBoardSqSize + 2;
  434.  
  435.     if (invertBoard) {
  436.         fromRow = 7 - fromRow;
  437.         fromCol = 7 - fromCol;
  438.     }
  439.     fromSq  = START_IBNDS + 10 * fromRow + fromCol;
  440.  
  441.     if (GameStatus(frHndl) != kGameContinues) return;
  442.         /* Game over, so no moves. */
  443.  
  444.     if ((*frHndl)->doc.resync != kIsMove) return;
  445.         /* Don't allow moves until we are resynced. */
  446.  
  447.     numLegalMoves = (*frHndl)->doc.numLegalMoves;
  448.     legalMoves    = (*frHndl)->doc.legalMoves;
  449.  
  450.     for (i = 0; i < numLegalMoves; ++i)
  451.         if ((**legalMoves)[i].moveFrom == fromSq) break;
  452.  
  453.     if (i == numLegalMoves) return;
  454.         /* Clicked on a empty square or on a piece that can't move. */
  455.  
  456.     myColor = (*frHndl)->doc.myColor;
  457.     if (twoPlayer)
  458.         if (WhosMove(frHndl) != myColor) return;
  459.             /* It's the other player's turn. */
  460.  
  461.     if ((myColor == WHITE) && ((*frHndl)->doc.compMovesWhite)) return;
  462.     if ((myColor == BLACK) && ((*frHndl)->doc.compMovesBlack)) return;
  463.         /* Computer is moving this color, so ignore click. */
  464.  
  465.     dragRgn = NewRgn();
  466.     RectRgn(dragRgn, &squareRect);
  467.     moveAmount = DragGrayRgn(dragRgn, clickLoc, &boardRect, &boardRect,
  468.                              noConstraint, nil);
  469.     DisposeRgn(dragRgn);
  470.  
  471.     if (moveAmount == 0x80008000L) return;
  472.  
  473.     releaseLoc.h = clickLoc.h + (moveAmount & 0xFFFF);
  474.     moveAmount   = moveAmount >> 16;
  475.     releaseLoc.v = clickLoc.v + (moveAmount & 0xFFFF);
  476.  
  477.     toRow = (releaseLoc.v - kBoardVOffset) / kBoardSqSize;
  478.     toCol = (releaseLoc.h - kBoardHOffset) / kBoardSqSize;
  479.     if (invertBoard) {
  480.         toRow = 7 - toRow;
  481.         toCol = 7 - toCol;
  482.     }
  483.     toSq  = START_IBNDS + 10 * toRow + toCol;
  484.  
  485.     for (i = 0; i < numLegalMoves; ++i)
  486.         if (
  487.             ((**legalMoves)[i].moveFrom == fromSq) &&
  488.             ((**legalMoves)[i].moveTo   == toSq)
  489.         ) break;
  490.  
  491.     if (i == numLegalMoves) return;        /* Tried an illegal move. */
  492.  
  493.     promotion = QUEEN;        /* If there is a promotion, assume queen. */
  494.  
  495.     if ((toRow == 0) || (toRow == 7)) {        /* Possible pawn promotion... */
  496.  
  497.         piece = (*frHndl)->doc.theBoard[fromSq];
  498.         if (piece < 0) piece = -piece;
  499.  
  500.         if (piece == PAWN) {                /* It is a pawn promotion... */
  501.             promoteDialog = GetCenteredDialog(rPawnPromotion, nil, nil, (WindowPtr)-1L);
  502.  
  503.             if (promoteDialog) {
  504.                 OutlineDialogItem(promoteDialog, 1);
  505.                 DoSetCursor(&QD(arrow));
  506.  
  507.                 for (item = QUEEN;;) {
  508.                     if (promotion != item) {
  509.                         GetDItem(promoteDialog, promotion + 1, &itemType, &itemHndl, &itemRect);
  510.                         SetCtlValue((ControlHandle)itemHndl, false);
  511.                     }
  512.  
  513.                     GetDItem(promoteDialog, item + 1, &itemType, &itemHndl, &itemRect);
  514.                     SetCtlValue((ControlHandle)itemHndl, true);
  515.                     promotion = item;
  516.  
  517.                     ModalDialog((ModalFilterProcPtr)keyEquivFilter, &item);
  518.                     if (item == 1) break;
  519.                     --item;
  520.                 }
  521.                 DisposDialog(promoteDialog);
  522.             }
  523.             SetPort(window);
  524.         }
  525.     }
  526.  
  527.     UpdateTime(frHndl, true);
  528.     MakeMove(frHndl, fromSq, toSq, promotion, true);
  529.     ImageDocument(frHndl, true);
  530.     DrawTime(frHndl);
  531.     AdjustGameSlider(frHndl);
  532.     DrawButtonTitle(frHndl, (*frHndl)->doc.twoPlayer);
  533.     UpdateGameStatus(frHndl);
  534.  
  535.     if (twoPlayer) SendGame(frHndl, kIsMove);
  536.     AlertIfGameOver(frHndl);
  537. }
  538.  
  539.  
  540.  
  541. /*****************************************************************************/
  542.  
  543.  
  544.  
  545. #pragma segment Main
  546. short    AlertIfGameOver(FileRecHndl frHndl)
  547. {
  548.     short    status;
  549.     Str255    gameStatMssg;
  550.  
  551.     if ((status = GameStatus(frHndl)) != kGameContinues) {
  552.         UpdateGameStatus(frHndl);
  553.         GetIndString(gameStatMssg, rGameStat, status);
  554.         ParamText(gameStatMssg, nil, nil, nil);
  555.         DoSetCursor(&QD(arrow));
  556.         CenteredAlert(rGameStat, nil);
  557.     }
  558.     return(status);
  559. }
  560.  
  561.  
  562.  
  563.